/*!
 Temelia - Vector samples.

 Copyright (C) 2008 Ceata (http://ceata.org/proiecte/temelia).

 @author Dascalu Laurentiu

 This program is free software; you can redistribute it and
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 3
 of the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include "include/samples.h"
#include <temelia/vector.h>

#define N 15

static void sample1()
{
	int *x, *y, i;
	vector_t vpb;
	vector_t vpf;

	PRINT("\n\n Sample 1 started \n\n");

	// vector push front and vector push back
	vpb = vector_new(N);
	vpf = vector_new(N);

	for (i = 0; i < N * N; i++)
	{
		x = int_new(i);
		vector_push_back(vpb, x);

		y = int_new(i);
		vector_push_front(vpf, y);
	}

	PRINT("Vector push back\n");
	vector_iterate(vpb, int_handler, NULL);

	PRINT("Vector push front\n");
	vector_iterate(vpf, int_handler, NULL);

	// Free the keys by iterating
	vector_iterate(vpb, int_delete, NULL);
	vector_iterate(vpf, int_delete, NULL);

	vector_delete(vpb);
	vpb = NULL;

	vector_delete(vpf);
	vpf = NULL;

	PRINT("\n\n Sample 1 ended \n\n");
}

static void sample2()
{
	int *x = NULL, i;
	vector_t v = NULL;

	PRINT("\n\n Sample 2 started \n\n");

	v = vector_new(N * N);
	vector_set_size(v, vector_get_capacity(v));
	vector_set_capacity_increment(v, N / 2);
	printf("%d %d %d\n", vector_get_size(v), vector_get_capacity(v),
			vector_get_capacity_increment(v));

	for (i = 0; i < N * N; i++)
	{
		x = int_new(rand() % 1000);
		vector_set_key_at(v, i, x);
	}

	PRINT("Before sorting\n");
	vector_iterate(v, int_handler, NULL);
	PRINT("\n");

	vector_sort(v, int_compare, NULL);

	PRINT("After sorting\n");
	vector_iterate(v, int_handler, NULL);

	vector_iterate(v, int_delete, NULL);

	vector_delete(v);
	v = NULL;

	PRINT("\n\n Sample 2 ended \n\n");
}

/*!
 * Inserts a lot of numbers and find the minimum and the maximum of the vector.
 * Demonstrates vector_min and vector_max.
 */
static void sample3()
{
	int *x = NULL, i;
	vector_t v = NULL;
	void **vector_internal_representation;

	PRINT("\n\n Sample 3 started \n\n");

	v = vector_new(N * N * N);

	for (i = 0; i < N * N * N * N; i++)
	{
		x = int_new(rand() % 1000);
		vector_push_back(v, x);
	}

	PRINT(" min = ");
	int_handler(vector_min(v, int_compare, NULL), NULL);
	PRINT("\n max = ");
	int_handler(vector_max(v, int_compare, NULL), NULL);

	// Free the allocated pointers
	vector_iterate(v, int_delete, NULL);

	vector_clear(v);
	vector_set_size(v, vector_get_capacity(v));

	for (i = 0; i < vector_get_size(v); i++)
	{
		x = vector_get_key_at(v, i);

		if (x)
		{
			PRINT("ERROR, vector_clear() failed!\n");
			exit(1);
		}
		else
		{
			x = int_new(0);
			vector_set_key_at(v, i, x);
		}
	}

	vector_iterate(v, int_delete, NULL);

	vector_internal_representation
			= (void **) vector_get_internal_representation(v);
	for (i = 0; i < vector_get_size(v); i++)
	{
		x = int_new(i);
		vector_internal_representation[i] = x;
	}

	//vector_iterate(v, int_handler, NULL);

	vector_iterate(v, int_delete, NULL);

	vector_delete(v);
	v = NULL;

	PRINT("\n\n Sample 3 ended \n\n");
}

static void sample4()
{
	int *x = NULL;
	vector_t v;

	PRINT("\n\n Sample 4 started \n\n");

	v = vector_new(N);

	while (!vector_is_full(v))
	{
		x = int_new(rand() % N);
		vector_push_front(v, x);
	}

	vector_set_capacity_increment(v, 0);
	vector_push_front(v, NULL);
	vector_push_back(v, NULL);
	PRINT("vector's size %d\n", vector_get_size(v));

	PRINT("vector before : ");
	vector_iterate(v, int_handler, NULL);

	PRINT("\nvector after : ");
	free(vector_remove_key(v, x, int_compare, NULL));
	free(vector_remove_key_at(v, 1));
	vector_iterate(v, int_handler, NULL);

	while (!vector_is_empty(v))
		free(vector_remove_key_at(v, vector_get_size(v) - 1));

	PRINT("\nvector's size/capacity : %d %d\n", vector_get_size(v),
			vector_get_capacity(v));

	vector_delete(v);
	v = NULL;

	PRINT("\n\n Sample 4 ended \n\n");
}

static void sample5()
{
	int *x, *y, i;
	vector_t v;

	PRINT("\n\n Sample 5 started \n\n");

	v = vector_new(N);

	x = int_new(0);
	vector_push_before(v, x, NULL, int_compare, NULL);

	x = int_new(1);
	vector_push_after(v, x, NULL, int_compare, NULL);

	y = int_new(2);
	vector_push_before(v, y, x, int_compare, NULL);

	y = int_new(3);
	vector_push_after(v, y, x, int_compare, NULL);

	PRINT("Before swap 0 and 2\n");
	vector_iterate(v, int_handler, NULL);

	vector_swap(v, 0, 2);

	PRINT("After swap\n");
	vector_iterate(v, int_handler, NULL);

	PRINT("\n");

	y = int_new(0);

	for (i = -5; i <= 5; i++)
	{
		*y = i;
		PRINT("%d %d\n", *y, vector_search(v, y, int_compare, NULL));
	}

	free(y);

	for (i = 1; i <= N / 2; i++)
	{
		x = int_new(i * i);
		vector_push_front(v, x);

		y = int_new(i * i * i);
		vector_push_front(v, y);
	}

	PRINT("Before pop_front and pop_back: \n");
	vector_iterate(v, int_handler, NULL);
	PRINT("\n");

	for (i = 0; i < N / 4; i++)
	{
		x = (int *) vector_pop_back(v);
		y = (int *) vector_pop_front(v);

		PRINT("%d %d\n", *x, *y);

		// No longer managed by the vector data structure
		free(x);
		free(y);
	}

	PRINT("After pop_front and pop_back: \n");
	vector_iterate(v, int_handler, NULL);

	vector_iterate(v, int_delete, NULL);

	vector_delete(v);

	PRINT("\n\n Sample 5 ended \n\n");
}

void run_vector_samples()
{
	sample1();
	sample2();
	sample3();
	sample4();
	sample5();
}
